#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
模型文件重构脚本
使用字段模板重构现有的DSL模型文件，减少重复定义
"""

import os
import yaml
import json
import shutil
from pathlib import Path
from typing import Dict, List, Any, Set
from datetime import datetime

def load_yaml_file(file_path: str) -> Dict[str, Any]:
    """加载YAML文件"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return yaml.safe_load(f) or {}
    except Exception as e:
        print(f"Error loading {file_path}: {e}")
        return {}

def save_yaml_file(file_path: str, data: Dict[str, Any]):
    """保存YAML文件"""
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            yaml.dump(data, f, default_flow_style=False, 
                     allow_unicode=True, indent=2, sort_keys=False)
    except Exception as e:
        print(f"Error saving {file_path}: {e}")

def load_template_examples() -> Dict[str, Any]:
    """加载模板使用示例"""
    examples_path = "examples/templates/template-usage-examples.json"
    if not os.path.exists(examples_path):
        print(f"Template examples not found: {examples_path}")
        return {}
    
    try:
        with open(examples_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        print(f"Error loading template examples: {e}")
        return {}

def create_backup(file_path: str) -> str:
    """创建文件备份"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_path = f"{file_path}.backup_{timestamp}"
    shutil.copy2(file_path, backup_path)
    return backup_path

def refactor_entity_with_templates(entity_name: str, entity_def: Dict[str, Any], 
                                 template_info: Dict[str, Any]) -> Dict[str, Any]:
    """使用模板重构实体定义"""
    refactored_entity = {}
    
    # 添加模板继承
    if template_info.get('applicable_templates'):
        refactored_entity['extends'] = template_info['applicable_templates']
    
    # 复制基本信息
    for key in ['description', 'identity']:
        if key in entity_def:
            refactored_entity[key] = entity_def[key]
    
    # 处理属性 - 只保留非模板字段
    template_fields = set()
    for fields in template_info.get('template_fields', {}).values():
        template_fields.update(fields)
    
    original_attributes = entity_def.get('attributes', {})
    refactored_attributes = {}
    
    for field_name, field_def in original_attributes.items():
        if field_name not in template_fields:
            refactored_attributes[field_name] = field_def
    
    if refactored_attributes:
        refactored_entity['attributes'] = refactored_attributes
    
    # 复制其他部分
    for key in ['associations', 'commands', 'events', 'indexes', 'uniqueConstraints']:
        if key in entity_def:
            refactored_entity[key] = entity_def[key]
    
    return refactored_entity

def refactor_model_file(file_path: str, template_examples: Dict[str, Any]) -> bool:
    """重构单个模型文件"""
    file_name = Path(file_path).stem
    
    if file_name not in template_examples:
        print(f"⚠️  No template examples found for {file_name}")
        return False
    
    # 加载原始文件
    original_data = load_yaml_file(file_path)
    if not original_data or 'entities' not in original_data:
        print(f"⚠️  Invalid model file: {file_path}")
        return False
    
    # 创建备份
    backup_path = create_backup(file_path)
    print(f"📁 Created backup: {backup_path}")
    
    # 重构数据
    refactored_data = {key: value for key, value in original_data.items() if key != 'entities'}
    refactored_data['entities'] = {}
    
    file_examples = template_examples[file_name]
    entities_refactored = 0
    
    for entity_name, entity_def in original_data['entities'].items():
        if entity_name in file_examples:
            # 使用模板重构
            template_info = file_examples[entity_name]
            refactored_entity = refactor_entity_with_templates(
                entity_name, entity_def, template_info
            )
            refactored_data['entities'][entity_name] = refactored_entity
            entities_refactored += 1
            print(f"  ✅ Refactored {entity_name} entity")
        else:
            # 保持原样
            refactored_data['entities'][entity_name] = entity_def
            print(f"  ➡️  Kept {entity_name} entity unchanged")
    
    # 保存重构后的文件
    save_yaml_file(file_path, refactored_data)
    
    print(f"✅ Refactored {file_path}: {entities_refactored} entities updated")
    return True

def validate_refactored_files(template_examples: Dict[str, Any]) -> Dict[str, Any]:
    """验证重构后的文件"""
    validation_results = {
        'total_files': 0,
        'successful_files': 0,
        'failed_files': [],
        'field_reduction': {'before': 0, 'after': 0},
        'template_usage': {}
    }
    
    models_dir = "models"
    
    for file_name, file_examples in template_examples.items():
        file_path = f"{models_dir}/{file_name}.yml"
        if not os.path.exists(file_path):
            continue
            
        validation_results['total_files'] += 1
        
        try:
            # 加载重构后的文件
            refactored_data = load_yaml_file(file_path)
            
            if not refactored_data or 'entities' not in refactored_data:
                validation_results['failed_files'].append(f"{file_name}: Invalid structure")
                continue
            
            # 验证每个实体
            file_valid = True
            for entity_name, example_data in file_examples.items():
                if entity_name not in refactored_data['entities']:
                    validation_results['failed_files'].append(
                        f"{file_name}: Missing entity {entity_name}"
                    )
                    file_valid = False
                    continue
                
                entity_def = refactored_data['entities'][entity_name]
                
                # 检查是否有extends字段
                if 'extends' not in entity_def:
                    validation_results['failed_files'].append(
                        f"{file_name}.{entity_name}: Missing extends field"
                    )
                    file_valid = False
                    continue
                
                # 统计字段减少
                validation_results['field_reduction']['before'] += example_data['original_fields']
                validation_results['field_reduction']['after'] += len(entity_def.get('attributes', {}))
                
                # 统计模板使用
                for template_name in entity_def['extends']:
                    validation_results['template_usage'][template_name] = \
                        validation_results['template_usage'].get(template_name, 0) + 1
            
            if file_valid:
                validation_results['successful_files'] += 1
                
        except Exception as e:
            validation_results['failed_files'].append(f"{file_name}: {str(e)}")
    
    # 计算优化效果
    if validation_results['field_reduction']['before'] > 0:
        reduction_percentage = (
            (validation_results['field_reduction']['before'] - 
             validation_results['field_reduction']['after']) 
            / validation_results['field_reduction']['before'] * 100
        )
        validation_results['field_reduction']['percentage'] = round(reduction_percentage, 2)
    
    return validation_results

def generate_refactor_report(validation_results: Dict[str, Any]):
    """生成重构报告"""
    report_lines = [
        "# 模型文件重构报告",
        "",
        f"**重构时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
        "",
        "## 📊 重构统计",
        "",
        f"- **处理文件数**: {validation_results['total_files']}",
        f"- **成功重构**: {validation_results['successful_files']}",
        f"- **失败文件**: {len(validation_results['failed_files'])}",
        f"- **字段减少**: {validation_results['field_reduction'].get('percentage', 0):.1f}%",
        f"  - 重构前字段总数: {validation_results['field_reduction']['before']}",
        f"  - 重构后字段总数: {validation_results['field_reduction']['after']}",
        f"  - 减少字段数: {validation_results['field_reduction']['before'] - validation_results['field_reduction']['after']}",
        "",
        "## 🏷️ 模板使用统计",
        ""
    ]
    
    # 模板使用统计
    for template_name, usage_count in sorted(validation_results['template_usage'].items(), 
                                           key=lambda x: x[1], reverse=True):
        report_lines.append(f"- **{template_name}**: {usage_count} 次使用")
    
    # 失败文件
    if validation_results['failed_files']:
        report_lines.extend([
            "",
            "## ❌ 失败文件",
            ""
        ])
        for failure in validation_results['failed_files']:
            report_lines.append(f"- {failure}")
    
    report_lines.extend([
        "",
        "## 📝 使用说明",
        "",
        "重构后的模型文件使用了字段模板来减少重复定义。要使用这些文件，需要：",
        "",
        "1. **加载模板解析器**:",
        "   ```typescript",
        "   import { TemplateResolver } from './src/dsl/template-resolver';",
        "   const resolver = new TemplateResolver();",
        "   await resolver.loadTemplates();",
        "   ```",
        "",
        "2. **解析模板化的DSL文件**:",
        "   ```typescript",
        "   const resolvedModel = await resolveDSLWithTemplates('models/user.yml');",
        "   ```",
        "",
        "3. **验证模板引用**:",
        "   ```typescript",
        "   const errors = await validateDSLTemplates('models/user.yml');",
        "   ```",
        "",
        "## 🔄 回滚说明",
        "",
        "如果需要回滚到原始版本，可以使用备份文件：",
        "",
        "```bash",
        "# 查看备份文件",
        "ls models/*.backup_*",
        "",
        "# 恢复特定文件",
        "cp models/user.yml.backup_YYYYMMDD_HHMMSS models/user.yml",
        "```"
    ])
    
    # 保存报告
    report_file = "docs/model-refactor-report.md"
    with open(report_file, 'w', encoding='utf-8') as f:
        f.write('\n'.join(report_lines))
    
    print(f"📄 重构报告已保存: {report_file}")

def main():
    """主函数"""
    print("🔄 开始重构模型文件...")
    
    # 加载模板示例
    template_examples = load_template_examples()
    if not template_examples:
        print("❌ 无法加载模板示例，请先运行 create-template-examples.py")
        return
    
    # 确保models目录存在
    models_dir = "models"
    if not os.path.exists(models_dir):
        print(f"❌ 模型目录不存在: {models_dir}")
        return
    
    # 重构每个文件
    refactored_files = 0
    for file_name in template_examples.keys():
        file_path = f"{models_dir}/{file_name}.yml"
        if os.path.exists(file_path):
            if refactor_model_file(file_path, template_examples):
                refactored_files += 1
        else:
            print(f"⚠️  File not found: {file_path}")
    
    print(f"\n✅ 重构完成! 处理了 {refactored_files} 个文件")
    
    # 验证重构结果
    print("\n🔍 验证重构结果...")
    validation_results = validate_refactored_files(template_examples)
    
    # 生成报告
    generate_refactor_report(validation_results)
    
    print(f"\n📊 重构总结:")
    print(f"   - 成功重构: {validation_results['successful_files']}/{validation_results['total_files']} 文件")
    print(f"   - 字段减少: {validation_results['field_reduction'].get('percentage', 0):.1f}%")
    print(f"   - 失败文件: {len(validation_results['failed_files'])}")
    
    if validation_results['failed_files']:
        print(f"\n❌ 失败文件:")
        for failure in validation_results['failed_files']:
            print(f"   - {failure}")

if __name__ == "__main__":
    main()